#pragma once

#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/wait.h>
#include "../comm/expand_file_exist.hpp"
#include "../comm/log.hpp"

using namespace Log;

// 编译模块
// 对从网络中收到的代码进行编译
namespace Complier
{
    class Complier
    {
    public:
        Complier()
        {
        }
        ~Complier()
        {
        }
        // 输入: 编译的文件名
        static bool complie(const std::string &file_name)
        {
            // 打开标准错误文件，将错误信息重定向至其中
            umask(0);
            int stderror = open(expand::Expand::ComplieError(file_name).c_str(), O_CREAT | O_WRONLY, 0644);
            if (stderror < 0)
            {
                logMessage(ERROR, "%s, %s, %d", "打开complie_error文件失败", __FILE__, __LINE__);
                exit(1);
            }
            // 把2赋值给stderror
            if (dup2(stderror, 2) == -1)
            {
                logMessage(ERROR, "%s, %s, %d", "重定向失败", __FILE__, __LINE__);
                close(stderror);
                exit(2);
            }
            pid_t id = fork();
            if (id < 0)
            {
                logMessage(ERROR, "%s|%s|%d", "fork error", __FILE__, __LINE__);
                close(stderror);
                return false;
            }
            else if (id == 0)
            {

                // child
                // 程序替换调用编译器
                // g++ -o target src -std=c++11
                // 可变参数列表以nullptr结尾
                execlp("g++", "g++", "-o", expand::Expand::Exe(file_name).c_str(), expand::Expand::Src(file_name).c_str(), "-D", "COMPILER_ONLINE", "-D", "COMPILER_RUN", "-std=c++11", nullptr);
                exit(1);
            }
            else
            {
                // parent
                waitpid(id, nullptr, 0); // 阻塞式等待
                // 父进程判断编译是否成功
                // 如何判断？ -- 查看错误文件中是否有信息，如果存在就成功
                // 每次要删除exe
                if (expand::FileExist::isFileExists(expand::Expand::Exe(file_name).c_str()))
                {
                    logMessage(DEBUG, "%s, %s, %d", "编译成功", __FILE__, __LINE__);
                    return true;
                }
            }
            logMessage(DEBUG, "%s, %s, %d", "编译失败", __FILE__, __LINE__);

            return false;
        }
    };
}